import numpy as np
import pandas as pd
import keras
from keras.models import Sequential
from keras.optimizers import SGD
from keras.layers import Dense, Dropout
# from keras.utils import np_utils
import matplotlib.pyplot as plt

import datetime as d


############# Callback Class ###############

class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = {'batch':[], 'epoch':[]}
        self.accuracy = {'batch':[], 'epoch':[]}
        self.val_loss = {'batch':[], 'epoch':[]}
        self.val_acc = {'batch':[], 'epoch':[]}

    def on_batch_end(self, batch, logs={}):
        self.losses['batch'].append(logs.get('loss'))
        self.accuracy['batch'].append(logs.get('acc'))
        self.val_loss['batch'].append(logs.get('val_loss'))
        self.val_acc['batch'].append(logs.get('val_acc'))

    def on_epoch_end(self, batch, logs={}):
        self.losses['epoch'].append(logs.get('loss'))
        self.accuracy['epoch'].append(logs.get('acc'))
        self.val_loss['epoch'].append(logs.get('val_loss'))
        self.val_acc['epoch'].append(logs.get('val_acc'))

    def loss_plot(self, loss_type):
        iters = range(len(self.losses[loss_type]))
        plt.figure()
        # acc
        plt.plot(iters, self.accuracy[loss_type], 'r', label='train acc')
        # loss
        plt.plot(iters, self.losses[loss_type], 'g', label='train loss')
        if loss_type == 'epoch':
            # val_acc
            plt.plot(iters, self.val_acc[loss_type], 'b', label='val acc')
            # val_loss
            plt.plot(iters, self.val_loss[loss_type], 'k', label='val loss')
        plt.grid(True)
        plt.xlabel(loss_type)
        plt.ylabel('acc-loss')
        plt.legend(loc="upper right")
        plt.show()

############# Callback Class ################

history = LossHistory()


batch_size = 120
epochs = 50

model = Sequential()
model.add(Dense(78, activation='relu', input_dim=7800))
model.add(Dropout(0.2))
model.add(Dense(1, activation='sigmoid'))
sgd = SGD(lr=0.001, momentum=0.9, decay=1e-06, nesterov=True)
model.compile(loss="binary_crossentropy", optimizer=sgd, metrics=['accuracy'])


############### 分批读取train_data.csv ###############

training_start_time = d.datetime.now().strftime("%Y.%m.%d-%H:%M:%S")

print("###############################################")
print("traing start time: ", training_start_time)
print("###############################################")

train_data = pd.read_table('/home/orient/PycharmProjects/OtSpeacherRecognization/train_data.csv', sep=',', chunksize=12000)
X_train = np.empty(shape=[0, 7800])
y_train = np.array([])
for data in train_data:
    data = data.sample(frac=1)
    X_train = np.row_stack((X_train, data.iloc[:, 0:-1]))
    y_train = np.append(y_train, data.iloc[:, -1])
    data = np.column_stack((X_train, y_train))
    print("-------------------Traning-------------------")
    model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.2, callbacks=[history])
    X_train = np.empty(shape=[0, 7800])
    y_train = np.array([])

model.save('/home/orient/PycharmProjects/OtSpeacherRecognization/model/test.h5')

history.loss_plot('epoch')

training_stop_time = d.datetime.now().strftime("%Y.%m.%d-%H:%M:%S")


print("###############################################")
print("traning start time: ", training_start_time)
print("traning stop time: ", training_stop_time)
print("###############################################")

############### 分批读取train_data.csv ###############
